diff --git a/papaparse.js b/papaparse.js
index b7fa8db..21c7521 100755
--- a/papaparse.js
+++ b/papaparse.js
@@ -203,6 +203,8 @@
 		}
 		_config.dynamicTyping = dynamicTyping;
 
+		_config.transform = isFunction(_config.transform) ? _config.transform : false;
+
 		if (_config.worker && Papa.WORKERS_SUPPORTED)
 		{
 			var w = newWorker();
@@ -976,7 +978,7 @@
 			if (needsHeaderRow())
 				fillHeaderFields();
 
-			return applyHeaderAndDynamicTyping();
+			return applyHeaderAndDynamicTypingAndTransformation();
 		}
 
 		function needsHeaderRow()
@@ -1028,9 +1030,21 @@
 			return value;
 		}
 
-		function applyHeaderAndDynamicTyping()
+		function parseTransform(field, value) {
+			if (_config.transform) {
+				if (_config.transform.length === 1) {
+					return _config.transform(value);
+				} else {
+					return _config.transform(field,value);
+				}
+			} else {
+				return value;
+			}
+		}
+
+		function applyHeaderAndDynamicTypingAndTransformation()
 		{
-			if (!_results || (!_config.header && !_config.dynamicTyping))
+			if (!_results || (!_config.header && !_config.dynamicTyping && !_config.transform))
 				return _results;
 
 			for (var i = 0; i < _results.data.length; i++)
@@ -1046,6 +1060,7 @@
 					if (_config.header)
 						field = j >= _fields.length ? '__parsed_extra' : _fields[j];
 
+					value = parseTransform(field, value);
 					value = parseDynamic(field, value);
 
 					if (field === '__parsed_extra')
diff --git a/tests/test-cases.js b/tests/test-cases.js
index 773635e..0e7bdeb 100644
--- a/tests/test-cases.js
+++ b/tests/test-cases.js
@@ -872,6 +872,66 @@ var PARSE_TESTS = [
 			errors: []
 		}
 	},
+	{
+		description: "Custom transform function converts all true and false strings to booleans regardless of case",
+		input: '"true","false","T","F"\r\n"TRUE","FALSE","True","False"',
+		config: {
+			transform: function(value) {
+				if(typeof value === "string" && value.toLowerCase() === "true") return true;
+				if(typeof value === "string" && value.toLowerCase() === "false") return false;
+				return value;
+			}
+		},
+		expected: {
+			data: [[true,false,"T","F"], [true, false, true, false]],
+			errors: []
+		}
+	},
+	{
+		description: "Custom transform function converts leading zero strings to number and empty strings to NULL",
+		input: '001,002,003\r\n,null,undefined',
+		config: {
+			transform: function(value) {
+				if ((/^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i).test(value)) {
+					return Number.parseFloat(value);
+				} else if (value === "") {
+					return null;
+				}
+				return value;
+			}
+		},
+		expected: {
+			data: [[1,2,3], [null,"null","undefined"]],
+			errors: []
+		}
+	},
+	{
+		description: "Custom transform function uses cache to determine whether to act on column",
+		input: 'A,B,C\r\n1,2,3\r\n4,5,6',
+		config: {
+			transform: function(field,value) {
+				if (!this.transformCache) {
+					this.transformCache = {};
+				} else if (this.transformCache[field] === true) {
+					return value + ".0";
+				} else if (this.transformCache[field] === false) {
+					return value;
+				}
+
+				if (field > 0) {
+					this.transformCache[field] = true;
+					return value + ".0";
+				} else {
+					this.transformCache[field] = false;
+					return value;
+				}
+			}
+		},
+		expected: {
+			data: [["A","B.0","C.0"], ["1","2.0","3.0"], ["4","5.0","6.0"]],
+			errors: []
+		}
+	},
 	{
 		description: "Blank line at beginning",
 		input: '\r\na,b,c\r\nd,e,f',