function invertBy( obj, opts, transform ) {
	var allowDupes;
	var keys;
	var len;
	var key;
	var val;
	var out;
	var cb;
	var v;
	var i;
	if ( !isObjectLike( obj ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be an object (except null). Value: `%s`.', obj ) );
	}
	allowDupes = true;
	if ( arguments.length === 2 ) {
		cb = opts;
	} else {
		if ( !isObject( opts ) ) {
			throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', opts ) );
		}
		if ( hasOwnProp( opts, 'duplicates' ) ) {
			allowDupes = opts.duplicates;
			if ( !isBoolean( allowDupes ) ) {
				throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'duplicates', allowDupes ) );
			}
		}
		cb = transform;
	}
	if ( !isFunction( cb ) ) {
		throw new TypeError( format( 'invalid argument. Last argument must be a function. Value: `%s`.', cb ) );
	}
	keys = objectKeys( obj );
	len = keys.length;
	out = {};
	if ( allowDupes ) {
		for ( i = 0; i < len; i++ ) {
			key = keys[ i ];
			val = cb( key, obj[ key ], obj );
			if ( !hasOwnProp( out, val ) ) {
				out[ val ] = key;
				continue;
			}
			v = out[ val ];
			if ( isArray( v ) ) {
				out[ val ].push( key );
			} else {
				out[ val ] = [ v, key ];
			}
		}
	} else {
		for ( i = 0; i < len; i++ ) {
			key = keys[ i ];
			val = cb( key, obj[ key ], obj );
			out[ val ] = key;
		}
	}
	return out;
}
Inverts an object, such that keys become values and values become keys, according to a transform function.

@param {ObjectLike} obj - input object
@param {Options} [opts] - function options
@param {boolean} [opts.duplicates=true] - boolean indicating whether to store duplicate keys
@param {Function} transform - transform function
@throws {TypeError} first argument must be object-like
@throws {TypeError} options argument must an an object
@throws {TypeError} last argument must be a function
@throws {TypeError} must provide valid options
@returns {Object} inverted object

@example
function transform( key, value ) {
    return key + value;
}
var obj = {
    'a': 'beep',
    'b': 'boop'
};
var out = invertBy( obj, transform );
// returns { 'abeep': 'a', 'bboop': 'b' }

@example
function transform( key, value ) {
    return value;
}
var obj = {
    'a': 'beep',
    'b': 'beep'
};
var out = invertBy( obj, transform );
// returns { 'beep': [ 'a', 'b' ] }

@example
function transform( key, value ) {
    return value;
}

var obj = {};
obj.a = 'beep';
obj.b = 'boop';
obj.c = 'beep'; // inserted after `a`

var opts = {
    'duplicates': false
};
var out = invertBy( obj, opts, transform );
// returns { 'beep': 'c', 'boop': 'b' }