DecodeHook
diff --git a/mapstructure.go b/mapstructure.go
index dae28dd..20941e1 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -19,6 +19,14 @@
 // DecoderConfig is the configuration that is used to create a new decoder
 // and allows customization of various aspects of decoding.
 type DecoderConfig struct {
+	// DecodeHook, if set, will be called before any decoding and any
+	// type conversion (if WeaklyTypedInput is on). This lets you modify
+	// the values before they're set down onto the resulting struct.
+	//
+	// If an error is returned, the entire decode will fail with that
+	// error.
+	DecodeHook func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
+
 	// If ErrorUnused is true, then it is an error for there to exist
 	// keys in the original map that were unused in the decoding process
 	// (extra keys).
@@ -144,9 +152,17 @@
 		return nil
 	}
 
+	if d.config.DecodeHook != nil {
+		// We have a DecodeHook, so let's pre-process the data.
+		var err error
+		data, err = d.config.DecodeHook(d.getKind(dataVal), d.getKind(val), data)
+		if err != nil {
+			return err
+		}
+	}
+
 	var err error
 	dataKind := d.getKind(val)
-
 	switch dataKind {
 	case reflect.Bool:
 		err = d.decodeBool(name, data, val)
diff --git a/mapstructure_test.go b/mapstructure_test.go
index 53aa5f8..8d86099 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -219,6 +219,42 @@
 	}
 }
 
+func TestDecode_DecodeHook(t *testing.T) {
+	t.Parallel()
+
+	input := map[string]interface{}{
+		"vint": "WHAT",
+	}
+
+	decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
+		if from == reflect.String && to != reflect.String {
+			return 5, nil
+		}
+
+		return v, nil
+	}
+
+	var result Basic
+	config := &DecoderConfig{
+		DecodeHook: decodeHook,
+		Result:     &result,
+	}
+
+	decoder, err := NewDecoder(config)
+	if err != nil {
+		t.Fatalf("err: %s", err)
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		t.Fatalf("got an err: %s", err)
+	}
+
+	if result.Vint != 5 {
+		t.Errorf("vint should be 5: %#v", result.Vint)
+	}
+}
+
 func TestDecode_Nil(t *testing.T) {
 	t.Parallel()