For MATLAB built-in data types, MATLAB always passes arguments 'by value' in the sense that any changes made to input arguments within a function are not visible to the respective variables in the caller workspace.
However, since passing huge chunks of data 'by value' is inefficient, MATLAB internally optimizes for some cases and passes by reference and only creates local copies if modifications are being made to these arguments.
In the case of passing structures or cell arrays, only the field or cell data being modified by the function will be passed "by value". When the function returns, (assuming that the modified structure or cell array is returned as an output argument of the function and are captured in the calling workspace's structure) the calling workspace's copy of the structure or cell array is replaced by the function's copy such that only the changed fields are altered. This is done to make copying more efficient. For example:
% This will modify the structure in the calling function's workspace.
largeStructure = myFunc(largeStructure);
% This will NOT modify the structure in the calling function's workspace.
% Simple function
function [myStructure] = myFunc(myStructure)
myStructure.x = myStructure.x^2;
For MATLAB classes, there is support for two kinds of classes: value classes and handle classes. Value classes act as though they were "passed by value" and Handle classes act as though they were "passed by reference".