The UI-Router is now shipped with support for custom types of params. There is updated and working version of your plunker.
So, we can adjust the state def like this:
app.config(function($stateProvider) {
  $stateProvider.state('list', {
    url: 'list?{filter:CoolParam}',
As we can see, the filter is now of type CoolParam. Here we will define it:
app.config(['$urlMatcherFactoryProvider', function($urlMatcherFactory) {
  $urlMatcherFactory.type('CoolParam',
  {
     name : 'CoolParam',
     decode: function(val)  { return typeof(val) ==="string" ? JSON.parse(val) : val;},
     encode: function(val)  { return JSON.stringify(val); },
     equals: function(a, b) { return this.is(a) && this.is(b) 
                                  && a.status === b.status && a.type == b.type },
     is: function(val)      { return angular.isObject(val) 
                                  && "status" in val && "type" in val },
  })
}]);
And now the {{$stateParams}} of a link like this:
<a ui-sref="list({filter: {status: 1, type:2}})">Click me to see params</a>
will return:
{"filter":{"status":1,"type":2}}
NOTE: In this case I made my life easier, and simply converted json into string. This means, that url encoded param will look like this:
#/list?filter=%7B%22status%22:1,%22type%22:2%7D
which is {"status":1,"type":2}
But we can provide also other ways how to express our filter object
Check it here
Also related Q & A:
So, the above solution is nicely working with filter as a JSON. But in case that we must have url like this ?filter[status]=1&filter[type]=2, we have to define the state differently. Each parameter must be declared as a separated simple type
$stateProvider.state('list2', {
    url: 'list2?state&type',
})
But in this case we would have it like this ?status=1&type=2. This mapping is also part of this plunker.