### Summary
tl;dr `utils.merge` break `transformResponse` and `transformRequest` behaviour in certain scenarios.


There are 3 parts of the problem.

#### Inconsistency between types in configs when setting `transform*` directly via `axiosInstance.defaults.transform*` and using `axios.create(config)`

The problem is that when setting directly one would set it as e.g. `axios.defaults.transformRequest = [f1, f2, f3]` but when passing the same _array_ via config it will get mergeda and become `{0: ƒ, 1: ƒ, 2: ƒ}`
```javascript
axios.create = function create (instanceConfig) {
  return createInstance(utils.merge(defaults, instanceConfig))
}
```
and the `merge` function forces the array to become an `Object` with numbers converted to strings as keys.
That of course breaks a quite simple situation showed even in [examples/transform-response/index.html](https://github.com/axios/axios/blob/master/examples/transform-response/index.html)
```javascript
transformResponse: axios.defaults.transformResponse.concat(function (data, headers) {
```
Theoretically it still works as we can access this object via `[number]` but it seems as not quite expected behaviour.
Additionality when using typescript `transformResponse?: AxiosTransformer | AxiosTransformer[];` becomes very not true ;) and even can be a big problem when using a type guard `if (transformResponse instanceof Array) {`

#### Wrong behavior when merging `defaults` with per request `config`
Because of the merge method and the array becoming an Object we might encounter a totally unexpected behaviour when using `axios.get('url', { transformResponse: mySpecialOneTimeTransform });`
```
a = ['1', '2']
b = ['3']
utils.merge(a,b)
{0: "3", 1: "2"}
```
IMO that is the least expected behaviour when passing config to single request.

And that brings us to the last problem.

#### The _by design_ problem
1. When creating an axios instance  - should the transforms be merged or overwritten. 
2. When passing a config per request - should the transforms be merged or overwritten.
   * merging - then there is no possibility to exceptionally not apply the default transforms [bad idea], also we should at least keep the order
   * overwriting - that's kinda ok, we could then add a new transform by taking the defaults and `concat` a new transformer(as shown in example)
   * adding new api methods to transform* for adding and removing functions (that's becoming weirdly similar to interceptors)
3. Do we really need to have `AxiosTransformer | AxiosTransformer[]` i suppose allowing only an array would be better. (That could be a breaking change, but probably acceptable as we are expecting release 1.0)

This issue is strongly connected with #1109 and might be connected with multiple defaults and config issues from the checklist in #1333.

Possibly quite a lot of this will be solved when checklist item `Substitute custom utils with lodash` is finished.

#### Context

- axios version: *e.g.: v0.17.1*
- Environment: *e.g.: node v8.9.3, windows 10*

test/specs/core/mergeConfig.spec.js
c[key] = { user: 'foo', pass: 'test' }
      expect(mergeConfig(a, b)).toEqual(c);
    });
    it('should merge ' + key + ' with defaults', function() {
      var a = {}, b = {}, c = {};
      a[key] = { user: 'foo', pass: 'bar' };
      b[key] = { pass: 'test' };
      c[key] = { user: 'foo', pass: 'test' };
      expect(mergeConfig(a, b)).toEqual(c);
    });
    it('should overwrite default ' + key + ' with a non-object value', function() {
      [false, null, 123].forEach(function(value) {
        var a = {}, b = {}, c = {};
        a[key] = { user: 'foo', pass: 'test' };
        b[key] = value;
        c[key] = value;
        expect(mergeConfig(a, b)).toEqual(c);
      });
    });
  });
  it('should allow setting other options', function() {
    var merged = mergeConfig(defaults, { timeout: 123 });
    expect(merged.timeout).toEqual(123);
  });
  it('should allow setting custom options', function() {
    var merged = mergeConfig(defaults, { foo: 'bar' });
    expect(merged.foo).toEqual('bar');
  });
});