code: function (obj, variables, mutate) {
          // if there is nothing to replace, we move on
          if (!(obj && _.isObject(obj))) {
              return obj;
          }
  
          // convert the variables to a substitutor object (will not reconvert if already substitutor)
          variables = Substitutor.box(variables, Substitutor.DEFAULT_VARS);
  
          var customizer = function (objectValue, sourceValue) {
              objectValue = objectValue || {};
              if (!_.isString(sourceValue)) {
                  _.forOwn(sourceValue, function (value, key) {
                      sourceValue[key] = customizer(objectValue[key], value);
                  });
  
                  return sourceValue;
              }
  
              return this.replaceSubstitutions(sourceValue, variables);
          }.bind(this);
  
          return _.mergeWith(mutate ? obj : {}, obj, customizer);
      }
docs: This function accepts an object followed by a number of variable sources as arguments. One or more variable
  sources can be provided and it will use the one that has the value in left-to-right order.
  
  @param {Object} obj
  @param {Array.<VariableList|Object>} variables
  @param {Boolean=} [mutate=false]
  @returns {Object}